/**
 * Copyright (c) 2018-2028, Chill Zhuang 庄骞 (smallchill@163.com).
 * <p>
 * Licensed under the GNU LESSER GENERAL PUBLIC LICENSE 3.0;
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 * <p>
 * http://www.gnu.org/licenses/lgpl.html
 * <p>
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package org.springblade.modules.policy.controller;

import com.alibaba.excel.EasyExcel;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.core.toolkit.StringUtils;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.github.xiaoymin.knife4j.annotations.ApiOperationSupport;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import io.swagger.annotations.ApiParam;
import lombok.AllArgsConstructor;
import org.springblade.common.constant.PolicyConstant;
import org.springblade.core.boot.ctrl.BladeController;
import org.springblade.core.mp.support.Condition;
import org.springblade.core.mp.support.Query;
import org.springblade.core.tool.api.R;
import org.springblade.core.tool.utils.Func;
import org.springblade.modules.enterprise.excel.AwardCorporateExcel;
import org.springblade.modules.policy.entity.*;
import org.springblade.modules.policy.excel.PolicyDrawExcel;
import org.springblade.modules.policy.mapper.PolicyMapper;
import org.springblade.modules.policy.service.*;
import org.springblade.modules.policy.vo.PolicyDrawPushVO;
import org.springblade.modules.policy.vo.PolicyDrawVO;
import org.springframework.beans.BeanUtils;
import org.springframework.web.bind.annotation.*;

import javax.servlet.http.HttpServletResponse;
import javax.validation.Valid;
import java.io.UnsupportedEncodingException;
import java.net.URLEncoder;
import java.nio.charset.StandardCharsets;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import java.util.stream.Collectors;

/**
 * 控制器
 *
 * @author Blade
 * @since 2022-07-25
 */
@RestController
@AllArgsConstructor
@RequestMapping("/blade-policy/policydraw")
@Api(value = "", tags = "接口")
public class PolicyDrawController extends BladeController {

	private IPolicyDrawService policyDrawService;

	private IPolicyService policyService;

	private PolicyMapper policyMapper;

	private IPolicyDrawMaterialService policyDrawMaterialService;

	private IPolicyDrawProcessService policyDrawProcessService;

	private IAuditRecordService auditRecordService;

	/**
	 * 详情
	 */
	@GetMapping("/detail")
	@ApiOperationSupport(order = 1)
	@ApiOperation(value = "详情", notes = "传入policyDraw")
	public R<PolicyDraw> detail(PolicyDraw policyDraw) {
		PolicyDraw detail = policyDrawService.getOne(Condition.getQueryWrapper(policyDraw));
		PolicyDrawVO policyDrawVO = new PolicyDrawVO();
		BeanUtils.copyProperties(detail, policyDrawVO);
		if (Func.isNotBlank(detail.getPolicys())) {
			String[] policyIds = detail.getPolicys().split(",");
			LambdaQueryWrapper<Policy> policyLambdaQueryWrapper = Wrappers.lambdaQuery();
			policyLambdaQueryWrapper.in(Policy::getId, (Object[]) policyIds);
			List<Policy> policies = policyMapper.selectList(policyLambdaQueryWrapper);
			policyDrawVO.setPolicyList(policies);
		}

		//申请材料
		LambdaQueryWrapper<PolicyDrawMaterial> policyDrawMaterialLambdaQueryWrapper = Wrappers.lambdaQuery();
		policyDrawMaterialLambdaQueryWrapper.eq(PolicyDrawMaterial::getMatterId, detail.getId());
		policyDrawVO.setMaterialList(policyDrawMaterialService.list(policyDrawMaterialLambdaQueryWrapper));

		//办理流程
		LambdaQueryWrapper<PolicyDrawProcess> policyDrawProcessesLambdaQueryWrapper = Wrappers.lambdaQuery();
		policyDrawProcessesLambdaQueryWrapper.eq(PolicyDrawProcess::getMatterId, detail.getId());
		policyDrawVO.setProcessesList(policyDrawProcessService.list(policyDrawProcessesLambdaQueryWrapper));
		return R.data(policyDrawVO);
	}

	/**
	 * 分页
	 */
	@GetMapping("/list")
	@ApiOperationSupport(order = 2)
	@ApiOperation(value = "分页", notes = "传入policyDraw")
	public R<IPage<PolicyDraw>> list(PolicyDraw policyDraw, Query query) {
		if(Func.isNotBlank(policyDraw.getImplemention())){
			String implemention = policyDraw.getImplemention();
			policyDraw.setImplemention(null);
			implemention = "%"+implemention+"%";
			return R.data(policyDrawService.page(Condition.getPage(query), Condition.getQueryWrapper(policyDraw).like("implemention", implemention)));
		}
		IPage<PolicyDraw> pages = policyDrawService.page(Condition.getPage(query), Condition.getQueryWrapper(policyDraw));
		return R.data(pages);
	}

	/**
	 * 自定义分页
	 */
	@GetMapping("/page")
	@ApiOperationSupport(order = 3)
	@ApiOperation(value = "分页", notes = "传入policyDraw")
	public R<IPage<PolicyDrawVO>> page(PolicyDrawVO policyDraw, Query query) {
		IPage<PolicyDrawVO> pages = policyDrawService.selectPolicyDrawPage(Condition.getPage(query), policyDraw);
		return R.data(pages);
	}

	/**
	 * 自定义分页
	 */
	@GetMapping("/pageAudit")
	@ApiOperationSupport(order = 3)
	@ApiOperation(value = "审核分页", notes = "传入policy")
	public R<IPage<PolicyDraw>> pageAudit(PolicyDraw policyDraw, Query query) {
		QueryWrapper<PolicyDraw> queryWrapper = Condition.getQueryWrapper(policyDraw);
		queryWrapper.eq("publish_status", PolicyConstant.POLICY_PUBLISH_STATUS_WAIT_CHECK);
		queryWrapper.or().eq("publish_status", PolicyConstant.POLICY_PUBLISH_STATUS_CHECK_FAIL);
		queryWrapper.or().eq("publish_status", PolicyConstant.POLICY_PUBLISH_STATUS_CHECK_PASS);
		IPage<PolicyDraw> pages = policyDrawService.page(Condition.getPage(query), queryWrapper);
		return R.data(pages);
	}

	/**
	 * 新增
	 */
	@PostMapping("/save")
	@ApiOperationSupport(order = 4)
	@ApiOperation(value = "新增", notes = "传入policyDraw")
	public R save(@Valid @RequestBody PolicyDraw policyDraw) {
		return R.status(policyDrawService.save(policyDraw));
	}

	/**
	 * 修改
	 */
	@PostMapping("/update")
	@ApiOperationSupport(order = 5)
	@ApiOperation(value = "修改", notes = "传入policyDraw")
	public R update(@Valid @RequestBody PolicyDraw policyDraw) {
		return R.status(policyDrawService.updateById(policyDraw));
	}

	/**
	 * 新增或修改
	 */
	@PostMapping("/submit")
	@ApiOperationSupport(order = 6)
	@ApiOperation(value = "新增或修改", notes = "传入policyDraw")
	public R submit(@Valid @RequestBody PolicyDrawVO policyDraw) {
		policyDraw.setPublishStatus(PolicyConstant.POLICY_PUBLISH_STATUS_WAIT_SUBMIT);
		return R.status(policyDrawService.saveAll(policyDraw));
	}


	/**
	 * 删除
	 */
	@PostMapping("/remove")
	@ApiOperationSupport(order = 7)
	@ApiOperation(value = "逻辑删除", notes = "传入ids")
	public R remove(@ApiParam(value = "主键集合", required = true) @RequestParam String ids) {
		return R.status(policyDrawService.deleteLogic(Func.toLongList(ids)));
	}

	/*
		事项状态修改
	 */
	@GetMapping("/change/{id}")
	public R changeStatus(@RequestParam String option, @PathVariable Long id) {

		PolicyDraw byId = policyDrawService.getById(id);
		if (option.equals("sub")) {
			if (byId.getPublishStatus() >= PolicyConstant.POLICY_PUBLISH_STATUS_WAIT_CHECK) {
				return R.fail("事项已提交");
			} else {
				byId.setPublishStatus(PolicyConstant.POLICY_PUBLISH_STATUS_WAIT_CHECK);
			}
		} else if (option.equals("push")) {
			if (byId.getPublishStatus() > PolicyConstant.POLICY_PUBLISH_STATUS_CHECK_PASS) {
				return R.fail("事项已发布");
			} else if (byId.getPublishStatus() < PolicyConstant.POLICY_PUBLISH_STATUS_CHECK_PASS) {
				return R.fail("事项未审核通过");
			}
			if (byId.getDeclareEnd().equals("长期有效")) {
				byId.setPublishStatus(PolicyConstant.POLICY_PUBLISH_STATUS_LONGTIME);
			} else {
				byId.setPublishStatus(PolicyConstant.POLICY_PUBLISH_STATUS_PROCESSING);
			}
		} else if (option.equals("unPush")) {
			if (byId.getPublishStatus() < PolicyConstant.POLICY_PUBLISH_STATUS_PROCESSING) {
				return R.fail("事项未发布");
			} else if (byId.getPublishStatus() > PolicyConstant.POLICY_PUBLISH_STATUS_LONGTIME) {
				return R.fail("事项已结束");

			} else {
				byId.setPublishStatus(PolicyConstant.POLICY_PUBLISH_STATUS_CHECK_PASS);
			}
		}
		return R.status(policyDrawService.updateById(byId));

	}

	/**
	 * 事项审核通过
	 * @param id
	 * @return
	 */
	@GetMapping("/pass/{id}")
	public R pass(@PathVariable Long id) {
		PolicyDraw byId = policyDrawService.getById(id);
		byId.setPublishStatus(PolicyConstant.POLICY_PUBLISH_STATUS_CHECK_PASS);
		return R.status(policyDrawService.updateById(byId));
	}
	/**
	 * 事项审核驳回
	 * @param
	 * @return
	 */
	@PostMapping("/reject")
	public R reject(@RequestBody AuditRecord auditRecord) {
		if (auditRecordService.save(auditRecord)) {
			PolicyDraw byId = policyDrawService.getById(auditRecord.getAuditId());
			byId.setPublishStatus(PolicyConstant.POLICY_PUBLISH_STATUS_CHECK_FAIL);
			return R.status(policyDrawService.updateById(byId));
		} else {
			return R.fail("操作失败");
		}

	}

	/*
		事项统计
	 */
	@GetMapping("/handleStatisticsAll")
	public R handleStatisticsAll(PolicyDraw policyDraw) {
		Map<String, Long> map = new ConcurrentHashMap<>(16);
		QueryWrapper<PolicyDraw> queryWrapper1 = Condition.getQueryWrapper(policyDraw);
		long allCount = policyDrawService.count(queryWrapper1);
		queryWrapper1.le("publish_status", PolicyConstant.POLICY_PUBLISH_STATUS_CHECK_PASS)
			.or()
			.eq("publish_status", PolicyConstant.POLICY_PUBLISH_STATUS_END);
		long unPush = policyDrawService.count(queryWrapper1);
		QueryWrapper<PolicyDraw> queryWrapper2 = Condition.getQueryWrapper(policyDraw);
		queryWrapper2.gt("publish_status", PolicyConstant.POLICY_PUBLISH_STATUS_CHECK_PASS);
		queryWrapper2.ne("publish_status", PolicyConstant.POLICY_PUBLISH_STATUS_END);
		long push = policyDrawService.count(queryWrapper2);
		map.put("all", allCount);
		map.put("unPush", unPush);
		map.put("push", push);
		return R.data(map);
	}
	/**
	 * 查找推送企业
	 */
	@GetMapping("/findPushEnterprise")
	public R findPushEnterprise(String policyDrawId) throws Exception{
		return R.data(policyDrawService.selectPushEnterprise(policyDrawId));
	}
	/**
	 * 发送短信推送
	 */
	@PostMapping("/sendPush")
	public R sendPush(@Valid @RequestBody PolicyDrawPushVO policyDrawPushVO) throws Exception{
		return R.status(policyDrawService.sendPush(policyDrawPushVO));
	}
	@GetMapping("/export")
	public void export(PolicyDraw policyDraw, HttpServletResponse response) throws Exception{
		QueryWrapper<PolicyDraw> queryWrapper = Condition.getQueryWrapper(policyDraw);
		List<PolicyDraw> list = policyDrawService.list(queryWrapper);
		List<PolicyDrawExcel> policyDrawExcels = list.stream()
			.map(policyDraw2 -> {
				try {
					return new PolicyDrawExcel(policyDraw2);
				} catch (Exception e) {
					// 处理构造PolicyDrawExcel时可能发生的异常
					// 此处简单处理为打印异常堆栈，实际应用中应根据具体需求进行处理
					e.printStackTrace();
					return null;
				}
			})
			.filter(policyDrawExcel -> policyDrawExcel != null) // 过滤掉构造失败的条目
			.collect(Collectors.toList());
		policyDrawExcels.forEach(policyDrawExcel -> {
			LambdaQueryWrapper<Policy> policyQueryWrapper = new LambdaQueryWrapper<>();
			policyQueryWrapper.in(StringUtils.isNotBlank(policyDrawExcel.getPolicy()),Policy::getId,policyDrawExcel.getPolicy().split(","));
			List<Policy> policies = policyService.list(policyQueryWrapper);
			policyDrawExcel.setPolicy(String.join(",",policies.stream().map(Policy::getPolicyName).collect(Collectors.toList())));
			List<PolicyDrawMaterial> policyDrawMaterials = policyDrawMaterialService.selectMaterial(policyDraw.getId());
			policyDrawExcel.setMaterial(String.join(" , ",policyDrawMaterials.stream().map(PolicyDrawMaterial::getMaterialName).collect(Collectors.toList())));
		});
		response.setContentType("application/vnd.ms-excel");
		response.setCharacterEncoding(StandardCharsets.UTF_8.name());
		String fileName = URLEncoder.encode("事项导出", StandardCharsets.UTF_8.name());
		response.setHeader("Content-disposition", "attachment;filename=" + fileName + ".xlsx");
		EasyExcel.write(response.getOutputStream(), PolicyDrawExcel.class).sheet("事项表").doWrite(policyDrawExcels);

	}
}
